home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 July: Mac OS SDK / Dev.CD Jul 99 SDK1.toast / Development Kits / Mac OS / QuickDraw3D 1.6 SDK / Mac SampleCode Previous / Geometry Samples- Mac / Skinny3DSample / ValueControls ƒ / ValueControls.c next >
Encoding:
C/C++ Source or Header  |  1999-05-18  |  10.9 KB  |  490 lines  |  [TEXT/MPS ]

  1. #include <Printing.h>
  2. #include <Windows.h>
  3. #include <Fonts.h>
  4. #include <Devices.h>
  5. #include <ToolUtils.h>
  6. #include <TextUtils.h>
  7. #include <LowMem.h>
  8. #include <SegLoad.h>
  9. #include <fp.h>
  10.  
  11. #include "ValueControls.h"
  12.  
  13. #define    kVCHeight    12
  14. #define kVCWidth    192
  15. #define kValuePos    142 // right edge (right flush)
  16. #define kDecHitPos    156
  17. #define kIncHitPos    172
  18. #define kResetWidth  36
  19.  
  20. enum { 
  21.     kSettingsDlog = 1280
  22. };
  23.  
  24. enum {
  25.     iVCtitle = 3,
  26.     iMinValue,
  27.     iMaxValue,
  28.     iStepSize,
  29.     iCurrentV
  30. };
  31.  
  32. // private structures
  33.  
  34. struct ValueCtlRec {
  35.     Str255        title;
  36.     float        initV;
  37.     float        currV;
  38.     float        mini;
  39.     float        maxi;
  40.     float        delta;
  41.     Point        titlePos;    // absolute window coordinates; initialized from ValueCtlCluster
  42.     Point        valuePos;
  43.     Rect        wholeRect;
  44.     Rect        incrHit;
  45.     Rect        decrHit;
  46.     long        lastClick;
  47.     Boolean        isCheckBox;
  48. };
  49. typedef struct ValueCtlRec ValueCtlRec, *VcPtr;
  50.  
  51. struct ValueCtlCluster {
  52.     OSType        idTag;
  53.     Str255        vTitle;
  54.     long        howMany;            // 1-based
  55.     Rect        frame;                // tries to position controls by itself; 
  56.                                     // may add scrollbars if required, later.
  57.     Rect        resetHit;
  58.     long        vcHeight;            // height of one ValueCtlRec in pixels
  59.     long        maxEntries;            // 1-based
  60.     VcPtr        vCtls[1];            // 0-based
  61. };
  62. typedef struct ValueCtlCluster ValueCtlCluster;
  63.  
  64. static VcPtr    NewValueCtl(Str255 title, float initV, float mini, float maxi, float delta);
  65. static void     DrawValueCtl(VcPtr v);
  66. static void        IncrementVC(VcPtr v);
  67. static void        DecrementVC(VcPtr v);
  68. static Boolean     DoSettingsDialog(VcPtr v);
  69.  
  70. // from TextUtils.h:
  71. extern pascal StringPtr C2PStr(Ptr cString);
  72. extern pascal Ptr P2CStr(StringPtr pString);
  73.  
  74. // from my dialog utilities:
  75. void    PutFloat(DialogPtr dlg, short item, float value);
  76. float    GetFloat(DialogPtr dlg, short item);
  77.  
  78. //----------------------------------------------------------------------
  79. VcPtr    NewValueCtl(Str255 title, float    initV, float mini, float maxi, float delta)
  80. {
  81.     VcPtr    v;
  82.     Rect        r;
  83.     
  84.     v = (VcPtr)NewPtr(sizeof(ValueCtlRec));
  85.     if (v != nil) {
  86.         BlockMove((Ptr)title, (Ptr)v->title, (long)title[0]+1);
  87.         v->initV = initV;
  88.         v->currV = initV;
  89.         v->mini  = mini;
  90.         v->maxi  = maxi;
  91.         v->delta = delta;
  92.         v->titlePos.h = 4;
  93.         v->titlePos.v = kVCHeight - 2;
  94.         v->valuePos.h = kValuePos;
  95.         v->valuePos.v = kVCHeight - 2;
  96.         SetRect(&v->wholeRect, 0, 0, kVCWidth, kVCHeight);
  97.         SetRect(&r, 0, 0, kVCHeight - 2, kVCHeight - 2);
  98.         OffsetRect(&r, kDecHitPos, 1);
  99.         v->decrHit    = r;
  100.         OffsetRect(&r, kIncHitPos - kDecHitPos, 0);
  101.         v->incrHit    = r;
  102.         v->lastClick = 0;
  103.         v->isCheckBox = ((mini == 0.0) && (maxi == 1.0) && (delta == 1.0));
  104.     }
  105.     return v;
  106. }
  107.  
  108. //----------------------------------------------------------------------
  109. VccPtr    NewVCluster(long tag, Str255 title, long numEntries, Rect *bounds)
  110. {
  111.     Rect    r = *bounds; // avoid side effects on bounds parameter!
  112.     long     size;
  113.     VccPtr     vcc;
  114.     
  115.     InsetRect(&r, 4, 4);
  116.     r.top += 4;
  117.     if ( (numEntries + 1) * kVCHeight > (r.bottom - r.top) )
  118.         return nil; // don't have enough space
  119.         
  120.     r.bottom = r.top + numEntries * kVCHeight + 10;
  121.     size = sizeof(ValueCtlCluster) + (numEntries - 1) * sizeof(VcPtr);
  122.     vcc = (VccPtr)NewPtr(size);
  123.     if (vcc != nil) {
  124.         vcc->idTag = tag;
  125.         BlockMove((Ptr)title, (Ptr)vcc->vTitle, (long)title[0] + 1);
  126.         vcc->howMany = 0;
  127.         vcc->frame = r;
  128.         vcc->vcHeight = kVCHeight;
  129.         vcc->maxEntries = numEntries;
  130.         SetRect(&r, 0, 0, kResetWidth, kVCHeight - 1);
  131.         OffsetRect(&r, vcc->frame.right - kResetWidth - 6, vcc->frame.top - 6);
  132.         vcc->resetHit = r;
  133.     }
  134.     return vcc;
  135. }
  136.  
  137.  
  138. //----------------------------------------------------------------------
  139. void AddValueCtl(VccPtr vcc, Str255 title, float initV, float mini, float maxi, float delta)
  140.  
  141. {
  142.     VcPtr    v;
  143.     Point    offset;
  144.     
  145.     if (vcc->howMany >= vcc->maxEntries)
  146.         return;
  147.     v = NewValueCtl(title, initV, mini, maxi, delta);
  148.     if (!v)
  149.         return;
  150.     offset.v = vcc->frame.top + (vcc->howMany + 1) * (vcc->vcHeight) - 6;
  151.     offset.h = vcc->frame.left + 2;
  152.     AddPt(offset, &v->titlePos);
  153.     AddPt(offset, &v->valuePos);
  154.     OffsetRect(&v->wholeRect, offset.h, offset.v);
  155.     SectRect(&vcc->frame, &v->wholeRect, &v->wholeRect);
  156.     v->wholeRect.right -= 2;
  157.     OffsetRect(&v->incrHit, offset.h, offset.v);
  158.     OffsetRect(&v->decrHit, offset.h, offset.v);
  159.     vcc->vCtls[vcc->howMany] = v;
  160.     vcc->howMany++;
  161. }
  162.  
  163. //----------------------------------------------------------------------
  164. void    AddSeparator(VccPtr vcc)
  165. {
  166.     AddValueCtl(vcc, "\p------------", 0.0,  0.0,  0.0, 0.0);
  167. }
  168.  
  169.  
  170. //----------------------------------------------------------------------
  171. Boolean    TakeHit(Point clickPt, VccPtr vcc)
  172. {
  173.     long         i, ticks;
  174.     Rect        r;
  175.     Boolean     isDblClick = false;
  176.     
  177.     i = 0;
  178.     r = vcc->resetHit;
  179.     if ( PtInRect(clickPt, &r) ) { // an afterthought ...
  180.         InvertRect(&r);
  181.          do {
  182.             vcc->vCtls[i]->currV = vcc->vCtls[i]->initV;
  183.             DrawValueCtl(vcc->vCtls[i]);
  184.         } while (++i < vcc->howMany);
  185.         InvertRect(&r);
  186.         return true;
  187.     }
  188.  
  189.     // i = 0;
  190.     
  191.     do {
  192.         if ((vcc->vCtls)[i]->mini < (vcc->vCtls)[i]->maxi) { 
  193.         // take hits only in real control lines
  194.             r = (vcc->vCtls)[i]->incrHit;
  195.             if ( PtInRect(clickPt, &r) ) {
  196.                 InvertRect(&r);
  197.                 IncrementVC((vcc->vCtls)[i]);
  198.                 goto newValue;
  199.             }
  200.             r = (vcc->vCtls)[i]->decrHit;
  201.             if ( PtInRect(clickPt, &r) ) {
  202.                 InvertRect(&r);
  203.                 DecrementVC((vcc->vCtls)[i]);
  204.                 goto newValue;
  205.             }
  206.             r = (vcc->vCtls)[i]->wholeRect;
  207.             if ( PtInRect(clickPt, &r) ) {
  208.                 ticks = ((vcc->vCtls)[i])->lastClick;
  209.                 isDblClick = (TickCount() - ticks < LMGetDoubleTime());
  210.                 ((vcc->vCtls)[i])->lastClick = TickCount();
  211.             }    
  212.             if ((isDblClick) && DoSettingsDialog((vcc->vCtls)[i])) {
  213.                 DrawValueCtl((vcc->vCtls)[i]);
  214.                 return true;
  215.             }
  216.             else
  217.                 isDblClick = false;
  218.         }
  219.     }  while ( (++i < vcc->howMany) );
  220.  
  221.     return false;
  222.     
  223. newValue:
  224.         Delay(6, &ticks);
  225.         InvertRect(&r);
  226.         ((vcc->vCtls)[i])->lastClick = TickCount();
  227.         DrawValueCtl((vcc->vCtls)[i]);
  228.         return true;
  229. }
  230.  
  231.  
  232. //----------------------------------------------------------------------
  233. static void    DrawValueCtl(VcPtr v)
  234. {
  235.     Str255        s;
  236.     Str255        st = "\ptrue";
  237.     Str255        sf = "\pfalse";
  238.     Rect        r;
  239.     long        w;
  240.     decimal        d;
  241.     decform        df;
  242.     
  243.     EraseRect(&v->wholeRect);
  244.     TextFont(geneva);
  245.     TextSize(9);
  246.     TextFace(0);
  247.     MoveTo(v->titlePos.h, v->titlePos.v);
  248.     DrawString(v->title);
  249.     if (v->mini == v->maxi) // separator
  250.         return;
  251.         
  252.     if (v->isCheckBox) {
  253.         if (v->currV == 1.0)
  254.             BlockMove(st, s, st[0]+1);
  255.         else
  256.             BlockMove(sf, s, sf[0]+1);
  257.     }
  258.     else {
  259.         df.style = FIXEDDECIMAL;
  260.         df.digits = 2;
  261.         num2dec(&df, v->currV, &d);
  262.         dec2str(&df, &d, (char *)s);
  263.         C2PStr((Ptr)s);
  264.     }
  265.     
  266.     TextFace(bold);
  267.     w = StringWidth(s);
  268.     MoveTo(v->valuePos.h - w, v->valuePos.v);
  269.     DrawString(s);
  270.  
  271.     r = v->incrHit;
  272.     FrameRect(&r);
  273.     if (v->isCheckBox) {
  274.         if (v->currV == 1.0) {
  275.             MoveTo(r.left, r.top);
  276.             LineTo(r.right - 1, r.bottom - 1);
  277.             MoveTo(r.left, r.bottom - 1);
  278.             LineTo(r.right - 1, r.top);
  279.         }
  280.     }
  281.     else {
  282.         MoveTo( r.left + 2, r.bottom - 2);
  283.         DrawChar('+');
  284.  
  285.         r = v->decrHit;
  286.         FrameRect(&r);
  287.         MoveTo(r.left + 2, r.bottom - 2);
  288.         DrawChar('-');
  289.     }
  290. }
  291.  
  292. //-----------------------------------
  293. static void    IncrementVC(VcPtr v)
  294. {
  295.     if (v->isCheckBox) {
  296.         if (v->currV == 0.0)
  297.             v->currV = 1.0;
  298.         else
  299.             v->currV = 0.0; 
  300.     }
  301.     else {
  302.         v->currV += v->delta;
  303.         if (v->currV > v->maxi)
  304.             v->currV = v->maxi;
  305.     }
  306. }
  307.  
  308.  
  309. //-----------------------------------
  310. static void    DecrementVC(VcPtr v)
  311. {
  312.     v->currV -= v->delta;
  313.     if (v->currV < v->mini)
  314.         v->currV = v->mini;
  315. }
  316.  
  317.  
  318. //----------------------------------------------------------------------
  319. //--------------------- ValueControlCluster routines -------------------
  320. //----------------------------------------------------------------------
  321. void    DrawVCluster(VccPtr    vcc)
  322. {
  323.     long     i;
  324.     Rect    r;
  325.     
  326.     FrameRect(&vcc->frame);
  327.     MoveTo(vcc->frame.left + 12, vcc->frame.top + 3);
  328.     TextFont(geneva);
  329.     TextSize(9);
  330.     TextFace(bold);
  331.     TextMode(srcCopy);
  332.     DrawChar(' '); DrawString(vcc->vTitle); DrawChar(' ');
  333.     r = vcc->resetHit;
  334.     EraseRect(&r);
  335.     FrameRect(&r);
  336.     MoveTo(r.left + 3, r.bottom - 2);
  337.     TextMode(srcOr);
  338.     DrawString("\pReset");
  339.     for (i = 0; i < vcc->howMany; i++)
  340.         DrawValueCtl(vcc->vCtls[i]);
  341. }
  342.  
  343. //----------------------------------------------------------------------
  344. void    DisposeVCluster(VccPtr    vcc)
  345. {
  346.     long i;
  347.     
  348.     for (i = 0; i < vcc->howMany; i++)
  349.         DisposePtr((Ptr)(&vcc->vCtls[i]));
  350.     DisposePtr((Ptr)vcc);
  351. }
  352.  
  353.  
  354. //----------------------------------------------------------------------
  355. OSType    GetIdTag(VccPtr    vcc)
  356. {
  357.     return vcc->idTag;
  358. }
  359.  
  360.  
  361. //----------------------------------------------------------------------
  362. float    GetCurrentValue(VccPtr vcc, long index)
  363. {
  364.     if ((index >= 0) && (index < vcc->howMany))
  365.         return     (vcc->vCtls[index])->currV;
  366.     else {
  367.         SysBeep(10);
  368.         return 0;
  369.     }
  370. }
  371.  
  372. //----------------------------------------------------------------------
  373. void    SetResetValue(VccPtr vcc, long index, float value)
  374. {
  375.     if ((index >= 0) && (index < vcc->howMany))
  376.         (vcc->vCtls[index])->initV = value;
  377.     else {
  378.         SysBeep(10);
  379.     }
  380. }
  381.  
  382.  
  383. //----------------------------------------------------------------------
  384. //---------------------   SettingsDialog routines   -------------------
  385. //----------------------------------------------------------------------
  386. static Boolean DoSettingsDialog(VcPtr v)
  387. {
  388.     DialogPtr        dlg;
  389.     GrafPtr            savePort;
  390.     ModalFilterUPP    filterProc;
  391.     OSErr            err;
  392.     short            item, kind;
  393.     Handle            h;
  394.     Rect            r;
  395.     
  396.     GetPort(&savePort);
  397.     dlg = GetNewDialog(kSettingsDlog, nil, (WindowPtr)(-1));
  398.     if (!dlg)
  399.         return false;
  400.     SetPort(dlg);    
  401.     err = GetStdFilterProc(&filterProc);
  402.     err = SetDialogDefaultItem(dlg, ok);
  403.     err = SetDialogCancelItem(dlg, cancel);
  404.     err = SetDialogTracksCursor(dlg, true);
  405.  
  406.     GetDialogItem(dlg, iVCtitle, &kind, &h, &r);
  407.     SetDialogItemText(h, v->title);
  408.     PutFloat(dlg, iMinValue, v->mini);
  409.     PutFloat(dlg, iMaxValue, v->maxi);
  410.     PutFloat(dlg, iStepSize, v->delta);
  411.     PutFloat(dlg, iCurrentV, v->currV);
  412.     
  413.     do {
  414.         ModalDialog(filterProc, &item);
  415.          switch (item) {
  416.          case ok: 
  417.          // range checks
  418.             break;
  419.         case iMinValue: 
  420.         // range check
  421.             break;
  422.         case iMaxValue:
  423.         // range check
  424.             break;
  425.         case iStepSize:
  426.         // range check
  427.             break;
  428.         case iCurrentV:
  429.         // range check
  430.             break;
  431.         }
  432.         if (item == ok) {
  433.             v->mini  = GetFloat(dlg, iMinValue);
  434.             v->maxi  = GetFloat(dlg, iMaxValue);
  435.             v->delta = GetFloat(dlg, iStepSize);
  436.             v->currV = GetFloat(dlg, iCurrentV);
  437.         }
  438.     } while ((item != cancel) && (item != ok));
  439.     
  440.     DisposeDialog(dlg);
  441.     SetPort(savePort);
  442.     return (item == ok);
  443. }
  444.  
  445.  
  446. //----------------------------------------------------------------------
  447. void    PutFloat(DialogPtr dlg, short item, float value)
  448. {
  449.     Str255        s;
  450.     Handle        h;
  451.     Rect        r;
  452.     decimal        d;
  453.     decform        df;
  454.     short        kind;
  455.     
  456.     df.style = FIXEDDECIMAL;
  457.     df.digits = 2;
  458.     num2dec(&df, value, &d);
  459.     dec2str(&df, &d, (char *)s);
  460.     C2PStr((Ptr)s);
  461.     GetDialogItem(dlg, item, &kind, &h, &r);
  462.     SetDialogItemText(h, s);
  463. }
  464.  
  465.  
  466. //----------------------------------------------------------------------
  467. float    GetFloat(DialogPtr dlg, short item)
  468. {
  469.     Str255        s;
  470.     Handle        h;
  471.     Rect        r;
  472.     decimal        d;
  473.     decform        df;
  474.     float        value = 0.0;
  475.     short        kind;
  476.     short        ix, vp;
  477.     
  478.     GetDialogItem(dlg, item, &kind, &h, &r);
  479.     if (h) {
  480.         GetDialogItemText(h, s);
  481.         P2CStr(s);
  482.         ix = 0;
  483.         str2dec((char *)s, &ix, &d, &vp);
  484.         if (vp) 
  485.             value = dec2f(&d);
  486.     }
  487.     return value;
  488. }
  489.  
  490.